//
//  IFlySpeechRecognizerManager.swift
//  GLUZSwift
//
//  Created by AI Assistant on 2024/12/19.
//  Copyright © 2024 考拉🐨. All rights reserved.
//

import Foundation
import UIKit

// MARK: - 语音识别结果回调协议
protocol MyIFlySpeechRecognizerDelegate: AnyObject {
    /// 识别结果回调
    /// - Parameters:
    ///   - result: 识别结果文本
    ///   - isLast: 是否为最后一个结果
    func speechRecognizerDidReceiveResult(_ result: String, isLast: Bool)
    
    /// 识别完成回调
    /// - Parameter error: 错误信息，nil表示成功
    func speechRecognizerDidComplete(_ error: Error?)
    
    /// 开始录音回调
    func speechRecognizerDidBeginRecording()
    
    /// 停止录音回调
    func speechRecognizerDidEndRecording()
    
    /// 音量变化回调
    /// - Parameter volume: 音量值 (0-30)
    func speechRecognizerDidChangeVolume(_ volume: Int)
    
    /// 取消识别回调
    func speechRecognizerDidCancel()
}

// MARK: - 语音识别语言枚举
enum IFlySpeechLanguage: String, CaseIterable {
    case chinese = "zh_cn"
    case russian = "ru-ru"
    
    var displayName: String {
        switch self {
        case .chinese:
            return "中文"
        case .russian:
            return "俄文"
        }
    }
}

// MARK: - 语音识别工具类
class IFlySpeechRecognizerManager: NSObject {
    
    // MARK: - 单例
    static let shared = IFlySpeechRecognizerManager()
    
    // MARK: - 属性
    private var speechRecognizer: IFlySpeechRecognizer?
    private var currentLanguage: IFlySpeechLanguage = .chinese
    private var isRecognizing = false
    private var isAudioFile = false
    
    // MARK: - 回调
    weak var delegate: MyIFlySpeechRecognizerDelegate?
    
    // MARK: - 初始化
    private override init() {
        super.init()
        setupSpeechRecognizer()
    }
    
    // MARK: - 私有方法
    private func setupSpeechRecognizer() {
        IFlySpeechUtility.createUtility("appid=9b1b2dfd")
        // 创建语音识别对象
        speechRecognizer = IFlySpeechRecognizer.sharedInstance()
        speechRecognizer?.delegate = self
        
        // 设置基本参数
        configureSpeechRecognizer()
    }
    
    private func configureSpeechRecognizer() {
        guard let recognizer = speechRecognizer else { return }
        
        // 设置APPID
        recognizer.setParameter("9b1b2dfd", forKey: IFlySpeechConstant.appid())
        
        // 设置语言
        recognizer.setParameter(currentLanguage.rawValue, forKey: IFlySpeechConstant.language())
        
        // 设置识别领域 - 普通文本听写
        recognizer.setParameter("iat", forKey: IFlySpeechConstant.ifly_DOMAIN())
        
        // 设置采样率
        recognizer.setParameter("16000", forKey: IFlySpeechConstant.sample_RATE())
        
        // 设置返回结果格式
        recognizer.setParameter("json", forKey: IFlySpeechConstant.result_TYPE())
        
        // 设置标点符号
        recognizer.setParameter("1", forKey: IFlySpeechConstant.asr_PTT())
        
        // 设置VAD前端点检测
        recognizer.setParameter("5000", forKey: IFlySpeechConstant.vad_BOS())
        
        // 设置VAD后端点检测
        recognizer.setParameter("5000", forKey: IFlySpeechConstant.vad_EOS())
        
        // 设置音频源为麦克风
        if (isAudioFile == true) {
            recognizer.setParameter("-1", forKey: IFlySpeechConstant.audio_SOURCE())
        } else {
            recognizer.setParameter("1", forKey: IFlySpeechConstant.audio_SOURCE())
        }
        
        
        // 设置引擎类型为云端
        recognizer.setParameter(IFlySpeechConstant.type_CLOUD(), forKey: IFlySpeechConstant.engine_TYPE())
    }
    
    // MARK: - 公共方法
    
    /// 设置识别语言
    /// - Parameter language: 语言类型
    func setLanguage(_ language: IFlySpeechLanguage) {
        currentLanguage = language
        speechRecognizer?.setParameter(language.rawValue, forKey: IFlySpeechConstant.language())
    }
    
    /// 设置音频文件路径并进行识别
    /// - Parameter path: 音频文件路径
    func setAudioPath(path: String) {
        guard let nsdata = NSData(contentsOfFile: path) else {
            xLog("音频文件数据失败")
            return
        }
        let data = nsdata as Data
        
        // 设置为音频文件模式
        isAudioFile = true
        
        // 延迟一点时间确保识别器准备就绪
        DispatchQueue.global().asyncAfter(deadline: .now()) { [weak self] in// 开始识别
            guard let self = self else { return }
            guard self.startListening() else {
                xLog("开始音频文件识别失败")
                return
            }
            self.writeAudioData(data)
        }
    }
    
    /// 写入音频数据
    /// - Parameter data: 音频数据
    private func writeAudioData(_ data: Data) {
        // 这里把data分割成长度为640的数据, 依次调用speechRecognizer?.writeAudio(subdata)
        let chunkSize = 1280
        var offset = 0
        
        while offset < data.count {
            let end = min(offset + chunkSize, data.count)
            let subdata = data.subdata(in: offset..<end)
            let result = speechRecognizer?.writeAudio(subdata)
            if (result == false) {
                xLog("讯飞写入音频流结果 \(result ?? false)")
            }
            offset += chunkSize
            
            // 添加小延迟，模拟实时音频流
//            usleep(5000) // 5ms延迟
        }
        
        // 写入完成后停止识别
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { [weak self] in
            self?.stopListening()
            self?.isAudioFile = false
        }
    }
    
    /// 开始语音识别
    /// - Returns: 是否开始成功
    @discardableResult
    func startListening() -> Bool {
        guard !isRecognizing else {
            print("语音识别正在进行中，请先停止当前识别")
            return false
        }
        
        guard let recognizer = speechRecognizer else {
            print("语音识别器未初始化")
            return false
        }
        
        // 重新配置参数
        configureSpeechRecognizer()
        
        let success = recognizer.startListening()
        if success {
            isRecognizing = true
            print("开始语音识别 - 语言: \(currentLanguage.displayName)")
        } else {
            print("开始语音识别失败")
        }
        
        return success
    }
    
    /// 停止语音识别
    func stopListening() {
        guard isRecognizing else {
            print("当前没有进行语音识别")
            return
        }
        
        speechRecognizer?.stopListening()
        print("停止语音识别")
    }
    
    /// 取消语音识别
    func cancelListening() {
        guard isRecognizing else {
            print("当前没有进行语音识别")
            return
        }
        
        speechRecognizer?.cancel()
        isRecognizing = false
        print("取消语音识别")
    }
    
    /// 检查是否正在识别
    var isListening: Bool {
        return isRecognizing
    }
    
    /// 销毁识别器
    func destroy() {
        speechRecognizer?.destroy()
        speechRecognizer = nil
        isRecognizing = false
        print("语音识别器已销毁")
    }
}

// MARK: - IFlySpeechRecognizerDelegate
extension IFlySpeechRecognizerManager: IFlySpeechRecognizerDelegate {
    
    @objc func onCompleted(_ errorCode: IFlySpeechError!) {
        isRecognizing = false
        
        if let error = errorCode {
            let errorMessage = "语音识别完成，错误码: \(error.errorCode), 错误描述: \(error.errorDesc ?? "未知错误")"
            print(errorMessage)
            delegate?.speechRecognizerDidComplete(NSError(domain: "IFlySpeechRecognizer", code: Int(error.errorCode), userInfo: [NSLocalizedDescriptionKey: error.errorDesc ?? "未知错误"]))
        } else {
            print("语音识别完成")
            delegate?.speechRecognizerDidComplete(nil)
        }
    }
    
    @objc func onResults(_ results: [Any]!, isLast: Bool) {
        guard let results = results, !results.isEmpty else {
            print("识别结果为空")
            return
        }
        
        // 解析识别结果
        var resultString = ""
        
        for result in results {
            if let dict = result as? [String: Any] {
                for (key, _) in dict {
                    resultString += key
                }
            }
        }
        
        print("识别结果: \(resultString), 是否最后结果: \(isLast)")
        
        // 解析 JSON 字符串
        guard let jsonData = resultString.data(using: .utf8) else {
            fatalError("无效的 JSON 字符串")
        }

        do {
            // 将 JSON 数据解析为字典
            if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                // 提取 "ws" 数组
                guard let wsArray = jsonDict["ws"] as? [[String: Any]] else {
                    fatalError("未找到 ws 字段")
                }
                
                // 遍历 ws 数组并提取所有 "w" 值
                var result = [String]()
                for wsItem in wsArray {
                    if let cwArray = wsItem["cw"] as? [[String: Any]] {
                        for cwItem in cwArray {
                            if let wValue = cwItem["w"] as? String {
                                result.append(wValue)
                            }
                        }
                    }
                }
                
                // 拼接结果字符串
                let finalString = result.joined(separator: "") // 用空格分隔
                print("提取结果：\(finalString)") // 输出：你好 你好
                delegate?.speechRecognizerDidReceiveResult(finalString, isLast: isLast)
            }
        } catch {
            print("解析失败：\(error.localizedDescription)")
            delegate?.speechRecognizerDidReceiveResult("解析失败", isLast: isLast)
        }
    }
    
    /// @param volume -[out] 音量，范围从0-30
    @objc func onVolumeChanged(_ volume: Int32) {
        let volumeInt = Int(volume)
        print("音量变化: \(volumeInt)")
        delegate?.speechRecognizerDidChangeVolume(volumeInt)
    }
    
    @objc func onBeginOfSpeech() {
        print("开始录音")
        delegate?.speechRecognizerDidBeginRecording()
    }
    
    @objc func onEndOfSpeech() {
        print("停止录音")
        delegate?.speechRecognizerDidEndRecording()
    }
    
    @objc func onCancel() {
        isRecognizing = false
        print("取消识别")
        delegate?.speechRecognizerDidCancel()
    }
}
